package com.coolw.spring.statemachine.config;

import com.coolw.spring.statemachine.constant.StateMachineConst;
import com.coolw.spring.statemachine.enums.OrderEvent;
import com.coolw.spring.statemachine.enums.OrderStatusEnum;
import com.coolw.spring.statemachine.support.order.OrderContext;
import com.coolw.spring.statemachine.support.order.OrderStateMachineAction;
import com.coolw.spring.statemachine.support.order.OrderStateMachineErrorAction;
import com.coolw.spring.statemachine.support.order.OrderStateMachineGuard;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.action.Action;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.guard.Guard;
import org.springframework.statemachine.state.State;

import javax.annotation.Resource;
import java.util.EnumSet;
import java.util.Objects;

/**
 * 订单状态机配置
 *
 * @author coolw
 * @date 2024/4/8 16:21
 */
@Slf4j
@Configuration
@EnableStateMachine(name = "orderStateMachine")
public class OrderStateMachineConfig extends StateMachineConfigurerAdapter<OrderStatusEnum, OrderEvent> {

    @Resource
    private OrderStateMachineGuard orderStateMachineGuard;

    @Resource
    private OrderStateMachineAction orderStateMachineAction;

    @Resource
    private OrderStateMachineErrorAction orderStateMachineErrorAction;

    /**
     * 配置状态
     */
    @Override
    public void configure(StateMachineStateConfigurer<OrderStatusEnum, OrderEvent> states) throws Exception {
        states
                .withStates()
                // 订单初始状态
                .initial(OrderStatusEnum.WAIT_PAYMENT)
                // 订单结束状态
                //.end(OrderStatusEnum.FINISH)
                // 订单所有状态
                .states(EnumSet.allOf(OrderStatusEnum.class));
    }

    /*@Override
    public void configure(StateMachineConfigurationConfigurer<OrderStatusEnum, OrderEvent> config) throws Exception {
        config
                .withConfiguration()
                // 设置状态执行策略为TIMEOUT_CANCEL,超时时间为10S
                .stateDoActionPolicy(StateDoActionPolicy.TIMEOUT_CANCEL)
                .stateDoActionPolicyTimeout(10, TimeUnit.SECONDS);
    }*/

    /**
     * 配置状态转换事件关系
     */
    @Override
    public void configure(StateMachineTransitionConfigurer<OrderStatusEnum, OrderEvent> transitions) throws Exception {
        transitions
                // 支付事件:待支付 -> 待发货
                .withExternal()
                .source(OrderStatusEnum.WAIT_PAYMENT).target(OrderStatusEnum.WAIT_DELIVER)
                .event(OrderEvent.PAYED)
                .guard(orderStateMachineGuard)
                //.action(orderStateMachineAction, orderStateMachineErrorAction)
                .and()
                // 发货事件:待发货 -> 待收货
                .withExternal()
                .source(OrderStatusEnum.WAIT_DELIVER).target(OrderStatusEnum.WAIT_RECEIVE)
                .event(OrderEvent.DELIVERY)
                .guard(orderStateMachineGuard)
                //.action(orderStateMachineAction, orderStateMachineErrorAction)
                .and()
                // 收货事件:待收货 -> 已完成
                .withExternal()
                .source(OrderStatusEnum.WAIT_RECEIVE).target(OrderStatusEnum.FINISH)
                .event(OrderEvent.RECEIVED)
                .guard(orderStateMachineGuard);
                //.action(orderStateMachineAction, orderStateMachineErrorAction);
    }

    /**
     * 使用Guard接口来保护状态转换
     */
    private Guard<OrderStatusEnum, OrderEvent> guard() {
        return context -> {
            OrderContext orderContext = (OrderContext) context.getMessageHeader(StateMachineConst.CONTEXT_KEY);
            if (Objects.isNull(orderContext)) {
                log.warn("orderContext为空,context:{}", context);
                return false;
            }
            return true;
        };
    }

    /**
     * 状态转换后,执行的操作
     */
    private Action<OrderStatusEnum, OrderEvent> doAction() {
        return (context) -> {
            OrderContext orderContext = (OrderContext) context.getMessageHeader(StateMachineConst.CONTEXT_KEY);
            State<OrderStatusEnum, OrderEvent> source = context.getSource();
            State<OrderStatusEnum, OrderEvent> target = context.getTarget();
            OrderEvent event = context.getEvent();
            log.info("订单操作,orderId:{},from:{},to:{},on:{}", orderContext.getOrderId(), source.getId(), target.getId()
                    , event);

            // 业务逻辑处理(例如:更新数据)
        };
    }

    /**
     * 状态转换错误的操作
     */
    private Action<OrderStatusEnum, OrderEvent> doErrorAction() {
        return (context) -> {
            OrderContext orderContext = (OrderContext) context.getMessageHeader(StateMachineConst.CONTEXT_KEY);
            State<OrderStatusEnum, OrderEvent> source = context.getSource();
            State<OrderStatusEnum, OrderEvent> target = context.getTarget();
            OrderEvent event = context.getEvent();
            Exception e = context.getException();
            log.error("订单操作异常,orderId:{},from:{},to:{},on:{}", orderContext.getOrderId(), source.getId(), target.getId()
                    , event, e);
        };
    }
}
